package com.sxy.tools;

import org.apache.commons.lang.StringUtils;

/**
 * 将数字金额转换为大写中文金额
 *
 * @author sxy
 */
public class ConvertUpMoney {

    /**
     * 大写数字
     */
    private static final String[] NUMBERS = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
    /**
     * 整数部分的单位
     */
    private static final String[] IUNIT = {"元", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "万", "拾", "佰", "仟"};
    /**
     * 小数部分的单位
     */
    private static final String[] DUNIT = {"角", "分", "厘"};

    /**
     * 零
     */
    private static final String ZERO = "0";

    /**
     * 小数点
     */
    private static final String DOT = ".";

    /**
     * 零点零
     */
    private static final String ZERO_DOT_ZERO = "0.0";

    /**
     * 零点零零
     */
    private static final String ZERO_DOT_ZERO_ZERO = "0.00";

    /**
     * 负号
     */
    private static final String NEGATIVE = "-";

    /**
     * 正则模式
     */
    private static final String REGEX = "(-)?[\\d]*(.)?[\\d]*";

    /**
     * 空字符串
     */
    private static final String EMPTY = "";

    /**
     * 逗号
     */
    private static final String COMMA = ",";


    /**
     * 转换为大写的中文金额
     *
     * @param moneyStr 金额字符串
     * @return 大写的中文金额
     */
    public static String toChinese(String moneyStr) {
        //初始化金额数字原样数据
        String initMoneyStr = moneyStr;
        //1.判断输入的金额字符串是否符合要求(-)?[\d]*(.)?[\d]*
        if (StringUtils.isBlank(moneyStr) || !moneyStr.matches(REGEX)) {
            //若金额字符串为空,或不符合金额要求,则原样返回
            return initMoneyStr;
        }
        //2.处理金额字符串数值为0的情况
        if (ZERO.equals(moneyStr) || ZERO_DOT_ZERO.equals(moneyStr) || ZERO_DOT_ZERO_ZERO.equals(moneyStr)) {
            return "零元";
        }

        //3.判断金额数字中是否存在负号"-"
        boolean flag = false;
        if (moneyStr.startsWith(NEGATIVE)) {
            //3.1.标志此金额数字为负数
            flag = true;
            moneyStr = moneyStr.replaceAll(NEGATIVE, EMPTY);
        }
        //4.去掉金额数字中的逗号","
        moneyStr = moneyStr.replaceAll(COMMA, EMPTY);
        //初始化 整数部分数字
        String integerStr;
        //初始化 小数部分数字
        String decimalStr;
        //5.分离整数部分和小数部分
        if (moneyStr.indexOf(DOT) > 0) {
            integerStr = moneyStr.substring(0, moneyStr.indexOf(DOT));
            decimalStr = moneyStr.substring(moneyStr.indexOf(DOT) + 1);
        } else if (moneyStr.indexOf(DOT) == 0) {
            integerStr = EMPTY;
            decimalStr = moneyStr.substring(1);
        } else {
            integerStr = moneyStr;
            decimalStr = EMPTY;
        }
        //6.beyond超出计算能力，直接原样返回
        if (integerStr.length() > IUNIT.length) {
            return initMoneyStr;
        }
        //7.整数部分数字
        int[] integers = toIntArray(integerStr);
        //8.判断整数部分是否存在输入012的情况
        if (integers.length > 1 && integers[0] == 0) {
            return initMoneyStr;
        }
        //9.设置万单位
        boolean isWan = isWan5(integerStr);
        //10.小数部分数字
        int[] decimals = toIntArray(decimalStr);
        //11.返回最终的大写金额
        String result = getChineseInteger(integers, isWan) + getChineseDecimal(decimals);
        if (flag) {
            //如果是负数，加上"负"
            return "负" + result;
        } else {
            return result;
        }
    }

    /**
     * 将字符串转为int数组
     *
     * @param number 字符串
     * @return int数组
     */
    private static int[] toIntArray(String number) {
        int[] array = new int[number.length()];
        for (int i = 0; i < number.length(); i++) {
            array[i] = Integer.parseInt(number.substring(i, i + 1));
        }
        return array;
    }

    /**
     * 将整数部分转为大写的金额
     *
     * @param integers 整数部分数字
     * @param isWan    整数部分是否已经是达到【万】
     * @return 整数部分大写金额
     */
    public static String getChineseInteger(int[] integers, boolean isWan) {
        StringBuilder chineseInteger = new StringBuilder();
        int length = integers.length;
        if (length == 1 && integers[0] == 0) {
            return EMPTY;
        }
        for (int i = 0; i < length; i++) {
            String key = EMPTY;
            if (integers[i] == 0) {
                //万（亿）
                if ((length - i) == 13) {
                    key = IUNIT[4];
                } else if ((length - i) == 9) {
                    //亿
                    key = IUNIT[8];
                } else if ((length - i) == 5 && isWan) {
                    //万
                    key = IUNIT[4];
                } else if ((length - i) == 1) {
                    //元
                    key = IUNIT[0];
                }
                if ((length - i) > 1 && integers[i + 1] != 0) {
                    key += NUMBERS[0];
                }
            }
            chineseInteger.append(integers[i] == 0 ? key : (NUMBERS[integers[i]] + IUNIT[length - i - 1]));
        }
        return chineseInteger.toString();
    }

    /**
     * 将小数部分转为大写的金额
     *
     * @param decimals 小数部分的数字
     * @return 中文大写小数部分
     */
    private static String getChineseDecimal(int[] decimals) {
        StringBuilder chineseDecimal = new StringBuilder();
        for (int i = 0; i < decimals.length; i++) {
            if (i == 3) {
                break;
            }
            chineseDecimal.append(decimals[i] == 0 ? "" : (NUMBERS[decimals[i]] + DUNIT[i]));
        }
        return chineseDecimal.toString();
    }

    /**
     * 判断当前整数部分是否已经是达到【万】
     *
     * @param integerStr 整数部分数字
     * @return 是否已经达到【万】
     */
    private static boolean isWan5(String integerStr) {
        int length = integerStr.length();
        if (length > 4) {
            String subInteger = "";
            if (length > 8) {
                subInteger = integerStr.substring(length - 8, length - 4);
            } else {
                subInteger = integerStr.substring(0, length - 4);
            }
            return Integer.parseInt(subInteger) > 0;
        } else {
            return false;
        }
    }


}

